/**
 *
 */
// 涉及的表名
const dbName = require("../config.js");
var dao = {};
var util = {};
// 初始化
dao.init = function(obj) {
	util = obj;
}
/**
 * 查 - 根据id获取单条记录
 * @params {String} id
 * @params {Object} fieldJson 字段显示规则
 * 调用示例
 * let goodsInfo = await vk.daoCenter.goodsDao.findById(_id);
 */
dao.findById = async (_id, fieldJson) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.findById({
		dbName: dbName.goods,
		id: _id,
		fieldJson
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};
/**
 * 查 - 根据id查,连表带出sku
 * @params {String} _id
 * 调用示例
 * let goodsInfo = await vk.daoCenter.goodsDao.findByIdHaveSkuList(_id);
 */
dao.findByIdHaveSkuList = async (_id) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await dao.selects({
		pageIndex:1,
		pageSize:1,
		getCount:false,
		getOne:true,
		getMain:true,
		whereJson:{
			_id
		},
		// 副表列表
		foreignDB:[
			{
				dbName:dbName.sku,
				localKey:"_id",
				foreignKey:"goods_id",
				as:"sku_list",
				limit:500
			}
		]
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};
/**
 * 查 - 根据ids查,连表带出sku
 * @params {array} ids
 * 调用示例
 * let goodsList = await vk.daoCenter.goodsDao.listByIdsHaveSkuList(ids);
 */
dao.listByIdsHaveSkuList = async (ids) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await dao.selects({
		pageIndex:1,
		pageSize:500,
		getCount:false,
		getMain:true,
		whereJson:{
			_id: _.in(ids)
		},
		// 副表列表
		foreignDB:[
			{
				dbName:dbName.sku,
				localKey:"_id",
				foreignKey:"goods_id",
				as:"sku_list",
				limit:500
			}
		]
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};
/**
 * 查 - 根据whereJson获取单条记录
 * @params {Object} whereJson 条件
 * @params {Object} fieldJson 字段显示规则
 * 调用示例
let goodsInfo = await vk.daoCenter.goodsDao.findByWhereJson({

});
 */
dao.findByWhereJson = async (whereJson, fieldJson) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.findByWhereJson({
		dbName: dbName.goods,
		whereJson,
		fieldJson
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 增 - 添加一条记录
 * @params {Object} dataJson 添加的数据
 * 调用示例
await vk.daoCenter.goodsDao.add({

});
 */
dao.add = async (dataJson) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.add({
		dbName: dbName.goods,
		dataJson
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 增 - 添加多条记录
 * @params {Object} dataJson 添加的数据
 * 调用示例
await vk.daoCenter.goodsDao.adds(dataArr);
 */
dao.adds = async (dataArr) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.adds({
		dbName: dbName.goods,
		dataJson: dataArr
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 删 - 删除多条记录
 * @params {Object} whereJson 条件
 * 调用示例
await vk.daoCenter.goodsDao.del({

});
 */
dao.del = async (whereJson) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.del({
		dbName: dbName.goods,
		whereJson
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 删 - 据ID删除单条数据
 * @params {String} id
 * 调用示例
await vk.daoCenter.goodsDao.deleteById(id);
 */
dao.deleteById = async (id) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.deleteById({
		dbName: dbName.goods,
		id
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 改 - 批量修改
 * @params {Object} whereJson 条件
 * @params {Object} dataJson 修改的数据
 * 调用示例
await vk.daoCenter.goodsDao.update({
	whereJson:{

	},
	dataJson:{

	}
});
 */
dao.update = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.update({
		...obj,
		dbName: dbName.goods,
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 改 - 根据ID修改数据
 * @param {String} _id
 * @param {Object} dataJson 修改的数据
 * 调用示例
await vk.daoCenter.goodsDao.updateById({
	id: _id,
	dataJson: {

	}
});
 */
dao.updateById = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.updateById({
		...obj,
		dbName: dbName.goods
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 改 - 更新并返回更新后的数据（无论条件匹配到多少条记录，只会修改第一条记录，同时返回修改后的数据）
 * @params {Object} whereJson 条件
 * @params {Object} dataJson 修改的数据
 * 调用示例
await vk.daoCenter.goodsDao.updateAndReturn({
	whereJson:{

	},
	dataJson:{

	}
});
 */
dao.updateAndReturn = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.updateAndReturn({
		...obj,
		dbName: dbName.goods
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 查 - 获取记录总条数
 * @params {Object} whereJson 条件
 * 调用示例
await vk.daoCenter.goodsDao.count(whereJson);
 */
dao.count = async (whereJson) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.count({
		dbName: dbName.goods,
		whereJson
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 查 - 获取数据列表
 * 调用示例
let goodsList = await vk.daoCenter.goodsDao.select({
	pageIndex:1,
	pageSize:20,
	getMain:false,
	whereJson:{

	},
	fieldJson:{},
	sortArr:[{ "name":"_id", "type":"desc" }],
});
 */
dao.select = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.select({
		...obj,
		dbName: dbName.goods
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 查 - 获取数据列表
 * 调用示例
let goodsList = await vk.daoCenter.goodsDao.selects({
	pageIndex:1,
	pageSize:20,
	getMain:false,
	whereJson:{

	},
	fieldJson:{},
	sortArr:[{ "name":"_id", "type":"desc" }],
	// 副表列表
	foreignDB:[
		{
			dbName:"副表表名",
			localKey:"主表外键名",
			foreignKey:"副表外键名",
			as:"副表as字段",
			limit:1
		}
	]
});
 */
dao.selects = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.selects({
		...obj,
		dbName: dbName.goods
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 查 - 获取数据列表
 * 调用示例
res = await vk.daoCenter.goodsDao.getTableData({ data });
 */
dao.getTableData = async (obj = {}) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	let { foreignDB = [] } = obj;
	res = await vk.baseDao.getTableData({
		...obj,
		dbName: dbName.goods,
		foreignDB: [
			...foreignDB,
			{
				dbName: dbName.sku,
				localKey: "_id",
				foreignKey: "goods_id",
				as: "sku_list",
				limit: 100
			}
		]
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 获取商品信息,浏览器+1.同时返回sku_list
 * 调用示例
await vk.daoCenter.goodsDao.findInfo(_id);
 */
dao.findInfo = async (_id) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	let goods = await vk.baseDao.updateAndReturn({
		dbName: dbName.goods,
		whereJson: {
			_id
		},
		dataJson: {
			view_count: _.inc(1)
		}
	});
	if (goods) {
		goods.sku_list = await vk.baseDao.select({
			dbName: dbName.sku,
			pageIndex: 1,
			pageSize: 500,
			getMain: true,
			whereJson: {
				goods_id: _id,
			}
		});
	}
	// 数据库操作结束-----------------------------------------------------------
	return goods;
};


/**
 * 获取商品的sku列表 根据sku_id
let sku_list = await vk.daoCenter.goodsDao.findSkuListByskuIds(sku_ids);
 */
dao.findSkuListByskuIds = async (sku_ids) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	// 查询SKU信息
	res = await vk.baseDao.selects({
		dbName: dbName.sku,
		getCount: false,
		getMain: true,
		pageSize: 100,
		fieldJson: {},
		whereJson: {
			_id: _.in(sku_ids)
		},
		// 副表列表
		foreignDB: [{
			dbName: dbName.goods, // 副表名
			localKey: "goods_id", // 主表外键字段名
			foreignKey: "_id", // 副表外键字段名
			as: "goodsInfo",
			limit: 1, // 当limit = 1时，以对象形式返回，否则以数组形式返回
		}]
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 扣除商品sku对应的库存 批量操作(不使用事务)
 * 调用示例
 let stockNumKey = await vk.daoCenter.goodsDao.updateSkuStockByskuList({
	 list : sku_list
 });
 *
 * res 返回参数说明
 * @params {Array<Object>} res sku列表
 */
dao.updateSkuStockByskuList = async (obj) => {
	let { vk, db, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let { list = [] } = obj;
	// 扣库存
	let decrStockSuccessList = []; // 记录已扣除成功的商品SKU
	for (let i in list) {
		let skuInfo = list[i];
		if (skuInfo.buy_num > 0) {
			let itemData = {
				sku_id: skuInfo._id,
				stock: skuInfo.buy_num,
				goods_id: skuInfo.goods_id
			};
			let num = await dao.updateSkuStockByskuId(itemData, 1);
			if (num <= 0) {
				res = { code: -1, msg: `商品（${skuInfo.goods_name} - ${skuInfo.sku_name}）库存不足！` };
				console.log("异常-高并发-有产品缺货了");
				break;
			} else {
				// 记录已扣除成功的商品SKU
				decrStockSuccessList.push(itemData);
			}
		}
	}
	if (res.code !== 0) {
		// 需要还原之前已扣除的库存
		for (let i in decrStockSuccessList) {
			let itemData = decrStockSuccessList[i];
			await dao.updateSkuStockByskuId(itemData, -1);
		}
	}
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 扣除商品sku对应的库存 根据sku_id 和 stock
 * 调用示例
 let num = await vk.daoCenter.goodsDao.updateSkuStockByskuId({
	 sku_id : sku_id,
	 stock : stock
 }, 1);
 */
dao.updateSkuStockByskuId = async (obj, k) => {
	let { vk, db, _ } = util;
	// sku_id="___"可以防止由于sku_id是undefined导致把所有商品的库存都改了
	let {
		sku_id = "___",
			stock = 0,
			goods_id = "___"
	} = obj;
	let res = 0;
	// 数据库操作开始-----------------------------------------------------------
	// 修改sku库存
	let num1 = await vk.baseDao.update({
		dbName: dbName.sku,
		whereJson: {
			_id: sku_id,
			stock: _.gte(stock * k)
		},
		dataJson: {
			stock: _.inc(stock * -1 * k)
		}
	});
	// 同步修改商品总库存
	let num2 = await vk.baseDao.updateById({
		dbName: dbName.goods,
		id: goods_id,
		dataJson: {
			stock: _.inc(stock * -1 * k)
		}
	});
	if (num1 > 0 && num2 > 0) {
		res = 1;
	}
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 增加商品sku对应的库存 批量操作
 * 调用示例
 await vk.daoCenter.goodsDao.addSkuStockByskuList(sku_list);
 */
dao.addSkuStockByskuList = async (sku_list) => {
	let { vk, db, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	// 扣库存
	for (let i in sku_list) {
		let skuInfo = sku_list[i];
		if (skuInfo.buy_num > 0 && skuInfo._id) {
			let itemData = {
				sku_id: skuInfo._id,
				stock: skuInfo.buy_num
			};
			await dao.updateSkuStockByskuId(itemData, -1);
		}
	}
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 增加商品sku对应的库存 批量操作
 * 调用示例
 await vk.daoCenter.goodsDao.addSkuStockByRefundGoodsList(goods_list);
 */
dao.addSkuStockByRefundGoodsList = async (goods_list) => {
	let { vk, db, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	// 扣库存
	for (let i in goods_list) {
		let skuInfo = goods_list[i];
		if (skuInfo.refund_num > 0 && skuInfo.sku_id) {
			let itemData = {
				sku_id: skuInfo.sku_id,
				stock: skuInfo.refund_num
			};
			await dao.updateSkuStockByskuId(itemData, -1);
		}
	}
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 批量修改商品和SKU的销量
 * 调用示例
 await vk.daoCenter.goodsDao.updateGoodsRealSellCountBySkuList(skuList);
 */
dao.updateGoodsRealSellCountBySkuList = async (skuList) => {
	let { vk, _ } = util;
	/*
	skuList的格式
	[{
		_id:"xxx", 			// sku id,
		goods_id:"xxx", // 商品id
		buy_num:1,			// 购买数量
	}]
	*/

	// skuList 按 buy_num 分组，减少执行数据库语句次数，让相同购买数量的商品一起修改
	let skuGroupObj = {};
	skuList.map((item, index) => {
		if (typeof skuGroupObj[item.buy_num] == "undefined") skuGroupObj[item.buy_num] = [];
		skuGroupObj[item.buy_num].push(item._id);
	});
	let goodsObj = {};
	skuList.map((item, index) => {
		if (typeof goodsObj[item.goods_id] == "undefined") goodsObj[item.goods_id] = 0;
		goodsObj[item.goods_id] += item.buy_num;
	});

	let goodsGroupObj = {};
	for (let goodsId in goodsObj) {
		let buy_num = goodsObj[goodsId];
		if (typeof goodsGroupObj[buy_num] == "undefined") goodsGroupObj[buy_num] = [];
		goodsGroupObj[buy_num].push(goodsId);
	}
	//console.log("skuGroupObj", JSON.stringify(skuGroupObj))
	//console.log("goodsGroupObj", JSON.stringify(goodsGroupObj))
	// 数据库操作开始-----------------------------------------------------------
	// 处理SKU销量
	for (let groupKey in skuGroupObj) {
		let groupList = skuGroupObj[groupKey];
		let buy_num = Number(groupKey);
		let skuIds = groupList.map((id) => {
			return id;
		});
		// 去重复
		skuIds = [...new Set(skuIds)];
		//console.log(buy_num, skuIds)
		// 修改SKU销量
		await vk.baseDao.update({
			dbName: dbName.sku,
			whereJson: {
				_id: _.in(skuIds)
			},
			dataJson: {
				real_sell_count: _.inc(buy_num), // 该sku的实际总销量（商家看到的）
			}
		});
	}
	// 处理商品销量
	for (let groupKey in goodsGroupObj) {
		let groupList = goodsGroupObj[groupKey];
		let buy_num = Number(groupKey);
		let goodsIds = groupList.map((id) => {
			return id;
		});
		// 去重复
		goodsIds = [...new Set(goodsIds)];
		//console.log(buy_num, goodsIds)
		// 修改商品销量
		await vk.baseDao.update({
			dbName: dbName.goods,
			whereJson: {
				_id: _.in(goodsIds)
			},
			dataJson: {
				real_sell_count: _.inc(buy_num), // 商品实际总销量（商家看到的）
				total_sell_count: _.inc(buy_num), // 商品显示的总销量（用户看到的）
			}
		});
	}
	// 数据库操作结束-----------------------------------------------------------
};

/**
 * 更新商品累计评价数量
 * 调用示例
await vk.daoCenter.goodsDao.updateCommentCount(_id);
 */
dao.updateCommentCount = async (_id) => {
	let { vk, db, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	// 获取商品累计评价数（只算审核通过的）
	let comment_count = await vk.daoCenter.goodsCommentDao.count({
		goods_id: _id,
		status: 1
	});
	// 修改商品累计评价数
	await vk.daoCenter.goodsDao.updateById({
		id: _id,
		dataJson: {
			comment_count
		}
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 查 - 求最大值
 * @param {String} fieldName 需要求最大值的字段名 
 * @param {Object} whereJson 筛选条件
 * 调用示例
let max = await vk.daoCenter.goodsDao.max({
	fieldName: "sort",
	whereJson: {
		
	}
});
 */
dao.max = async (obj) => {
	let { vk, db, _ } = util;
	let res = {};
	// 数据库操作开始-----------------------------------------------------------
	res = await vk.baseDao.max({
		...obj,
		dbName: dbName.goods,
	});
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


module.exports = dao;
